package dao

import (
	"context"
	"time"

	"github.com/bwmarrin/snowflake"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

var (
	ErrMongoRecodeNotFound = mongo.ErrNoDocuments
)

type ComicDAO interface {
	Insert(ctx context.Context, comic Comic) (int64, error)
	GetByUid(ctx context.Context, uid int64, offset int, limit int) ([]Comic, error)
	DeleteById(ctx context.Context, comicId int64, uid int64) error
}

type MongoDBComicDAO struct {
	node *snowflake.Node
	col  *mongo.Collection
}

func NewMongoDBComicDAO(mdb *mongo.Database, node *snowflake.Node) *MongoDBComicDAO {
	return &MongoDBComicDAO{
		node: node,
		col:  mdb.Collection("comic"),
	}
}

func (m *MongoDBComicDAO) DeleteById(ctx context.Context, comicId int64, uid int64) error {
	// 创建查询条件，根据漫画ID和用户ID筛选
	// 这样可以确保只有漫画作者本人才能删除
	filter := map[string]interface{}{
		"id":  comicId,
		"uid": uid,
	}

	// 执行删除操作
	result, err := m.col.DeleteOne(ctx, filter)
	if err != nil {
		return err
	}

	// 检查是否找到并删除了记录
	if result.DeletedCount == 0 {
		return mongo.ErrNoDocuments
	}

	return nil
}

func (m *MongoDBComicDAO) Insert(ctx context.Context, comic Comic) (int64, error) {
	now := time.Now().Unix()
	comic.Ctime = now
	comic.Utime = now
	comic.Id = m.node.Generate().Int64()
	_, err := m.col.InsertOne(ctx, &comic)

	return comic.Id, err
}

func (m *MongoDBComicDAO) GetByUid(ctx context.Context, uid int64, offset int, limit int) ([]Comic, error) {
	// 创建查询条件，根据用户ID筛选
	filter := map[string]interface{}{
		"uid": uid,
	}

	// 创建排序选项，按创建时间降序排列
	sort := map[string]interface{}{
		"ctime": -1,
	}

	// 执行查询
	cursor, err := m.col.Find(ctx, filter, options.Find().SetSort(sort).SetSkip(int64(offset)).SetLimit(int64(limit)))
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析结果
	var comics []Comic
	if err = cursor.All(ctx, &comics); err != nil {
		return nil, err
	}

	return comics, nil
}

type Comic struct {
	Id int64 `bson:"id,omitempty"`

	Uid        int64  `bson:"uid"`
	Text       string `bson:"content,omitempty"`
	Style      string `bson:"style,omitempty"`
	Tone       string `bson:"tone,omitempty"`
	Gender     string `bson:"gender,omitempty"`
	Appearance string `bson:"appearance,omitempty"`
	Draws      []Draw `bson:"draws,omitempty"`

	Ctime int64 `bson:"ctime,omitempty"`
	Utime int64 `bson:"utime,omitempty"`
}

type Draw struct {
	Desc string `bson:"desc,omitempty"`
	Url  string `bson:"url,omitempty"`
}
